﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web;
using Microsoft.SharePoint;
using WeMakeSP.ImageResizer.Configuration;
using WeMakeSP.ImageResizer.Services.ServiceContract;
using WeMakeSP.ImageResizer.Services.ServiceImplementation;
using WeMakeSP.Platform.Drawing;
using WeMakeSP.Platform.SharePoint.Configuration;
using System.Threading;

namespace WeMakeSP.ImageResizer
{
    /// <summary>
    /// The logic for the policies
    /// when uploading images.
    /// </summary>
    public class ImageUploadPolicy : IImageUploadPolicy
    {
        #region Fields

        /// <summary>
        /// The current web field.
        /// </summary>
        private SPWeb currentWebField;

        /// <summary>
        /// The image resizer service field.
        /// </summary>
        private IImageResizerService imageResizerServiceField;

        /// <summary>
        /// The item field.
        /// </summary>
        private SPListItem itemField;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ImageUploadPolicy"/> class.
        /// </summary>
        private ImageUploadPolicy()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ImageUploadPolicy"/> class.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="item">The item.</param>
        public ImageUploadPolicy(SPWeb web, SPListItem item)
            : this()
        {
            // Guard.

            if (web == null)
            {
                throw new ArgumentNullException("web");
            }

            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            this.currentWebField = web;

            this.itemField = item;
        }

        #endregion

        #region Protected Properties


        /// <summary>
        /// Gets the image resizer service.
        /// </summary>
        /// <value>The image resizer service.</value>
        protected IImageResizerService ImageResizerService
        {
            get
            {
                if (this.imageResizerServiceField == null)
                {
                    this.imageResizerServiceField =
                        new ImageResizerService(this.currentWebField);
                }

                return
                    this.imageResizerServiceField;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Applies the policy.
        /// </summary>
        public void ApplyPolicies()
        {
            // Get the list id.

            Guid listId =
                this.itemField.ParentList.ID;

            // Get configurations.

            ImageResizerPictureLibraryConfiguration configuration =
                this.ImageResizerService.GetPictureLibraryConfiguration(listId);

            // The configuration is enabled?

            if (configuration.Active == true)
            {
                // Get the image size.

                // TODO Check if the item is really an image, other file types
                // will raise an exception here.

                int beforeWidth =
                    int.Parse(this.itemField.Properties["vti_lastwidth"].ToString());
                int beforeHeight =
                    int.Parse(this.itemField.Properties["vti_lastheight"].ToString());

                // Get a reference to the file.

                SPFile picture =
                    this.itemField.File;

                switch (configuration.Action)
                {
                    case ImageResizerAction.Deny:

                        if (beforeWidth > configuration.MaxWidth || beforeHeight > configuration.MaxHeight)
                        {
                            // TODO create an exception.

                            throw new Exception("The image is too big!!!");
                        }

                        break;
                    case ImageResizerAction.Resize:

                        switch (configuration.Mode)
                        {
                            case ImageResizerMode.Resize:

                                using (System.IO.Stream pictureStream = picture.OpenBinaryStream())
                                {
                                    Bitmap bitmap =
                                        new Bitmap(pictureStream);

                                    Bitmap resizedBitmap =
                                        bitmap.Resize(configuration.MaxWidth, configuration.MaxHeight);

                                    using (System.IO.Stream resizedPictureStream = new System.IO.MemoryStream())
                                    {
                                        resizedBitmap.Save(resizedPictureStream, bitmap.RawFormat);

                                        picture.SaveBinary(resizedPictureStream);
                                    }
                                }

                                break;

                            case ImageResizerMode.ResizeProportional:

                                using (System.IO.Stream pictureStream = picture.OpenBinaryStream())
                                {
                                    Bitmap bitmap =
                                        new Bitmap(pictureStream);

                                    Bitmap resizedBitmap =
                                        bitmap.ResizeProportional(configuration.MaxWidth, configuration.MaxHeight);

                                    using (System.IO.Stream resizedPictureStream = new System.IO.MemoryStream())
                                    {
                                        resizedBitmap.Save(resizedPictureStream, bitmap.RawFormat);

                                        picture.SaveBinary(resizedPictureStream);
                                    }
                                }

                                break;

                            default:
                                throw new NotImplementedException("ImageResizerMode");
                        }

                        break;
                    default:
                        throw new NotImplementedException("ImageResizerAction");
                }

                bool success = false;

                for (int i = 0; i < 100 && success == false; i++)
                {
                    try
                    {
                        this.itemField.SystemUpdate(false);
                        success = true;
                    }
                    catch (SPException)
                    {
                        System.Threading.Thread.Sleep(500);
                    }
                }
            }
        }

        #endregion

        #region Private Methods
        #endregion
    }
}
